package client

import (
	"echo_client/pkg/model"
	"fmt"
	"time"

	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/shirou/gopsutil/v3/host"
	"github.com/shirou/gopsutil/v3/mem"
)

const (
	typKb  = 1000.0000
	typMib = 1000000.0000
	typGb  = 1000000000.0000
)

// unitToStr .
func unitToStr(num uint64, typ float64) (str string) {
	typeName := ""
	switch typ {
	case typKb:
		typeName = "KB"
	case typMib:
		typeName = "MB"
	case typGb:
		typeName = "GB"
	default:
		return ""
	}
	return fmt.Sprintf("%.2f%s", float64(num)/typ, typeName)
}

// MemoryInfo 内存信息
func (c *Client) MemoryInfo() *model.SystemMemory {
	v, err := mem.VirtualMemory()
	if err != nil {
		c.Error <- err
		return nil
	}
	return &model.SystemMemory{
		Total:       unitToStr(v.Total, typGb),
		Available:   unitToStr(v.Available, typGb),
		Used:        unitToStr(v.Used, typGb),
		Free:        unitToStr(v.Free, typGb),
		UsedPercent: fmt.Sprintf("%.2f%%", v.UsedPercent),
	}
}

// CpuInfo cpu信息
func (c *Client) CpuInfo() []model.SystemCpu {
	info, err := cpu.Info()
	if err != nil {
		c.Error <- err
		return nil
	}
	// cpu利用率
	percent, err := cpu.Percent(0, true)
	if err != nil {
		c.Error <- err
		return nil
	}
	cpus := make([]model.SystemCpu, 0, 1)
	for i := range info {
		cpus = append(cpus, model.SystemCpu{
			ModelName: info[i].ModelName,
			Cores:     fmt.Sprintf("%d", info[i].Cores),
			Mhz:       fmt.Sprintf("%.2fMhz", info[i].Mhz),
			Percent:   fmt.Sprintf("%.2f%%", percent[i]),
		})
	}
	return cpus
}

// HostInfo 主机信息
func (c *Client) HostInfo() *model.SystemHost {
	info, err := host.Info()
	if err != nil {
		c.Error <- err
		return nil
	}
	return &model.SystemHost{
		Name:     info.Hostname,
		Uptime:   info.Uptime,
		BootTime: info.BootTime,
		Os:       info.OS,
		Platform: fmt.Sprintf("%s-%s %s", info.Platform, info.PlatformVersion, info.PlatformFamily),
		Kernel:   info.KernelArch,
	}
}

// GetSystemInfo 获取系统信息
func (c *Client) GetSystemInfo() *model.SystemInfo {
	return &model.SystemInfo{
		Memory: c.MemoryInfo(),
		Cpu:    c.CpuInfo(),
		Host:   c.HostInfo(),
	}
}

// SendSystemInfo 发送当前系统信息
func (c *Client) SendSystemInfo(msg *model.MessageV1) {
	systemInfo := c.GetSystemInfo()
	v1 := model.NewMessageV1(model.ScMachineMessage, time.Now().Unix(), msg.Secret, "", msg.From, systemInfo)
	c.SendOneMsg(v1.ToProtobuf())
}
